/* 请求方法 */
import { ref, watch, getCurrentInstance, inject } from "vue";
import appConfig from "../../app.config";
import type { ModelType, ParamsType, ReturnDataType } from "@/types/model";

// 定义 InvokeAsyncConfigType 类型
export type InvokeAsyncConfigType = {
  noResponse: boolean;
};

// 定义 InvokeAsyncType 类型
export type InvokeAsyncType = <T>(
  methodName: string,
  params: ParamsType,
  config?: InvokeAsyncConfigType
) => Promise<T>;

export default function useInvokeAsync(): InvokeAsyncType {
  // const invokeAsync = inject<InvokeAsyncType>("invokeAsync");
  // if (!invokeAsync) {
  //   throw new Error("invokeAsync is not provided");
  // }
  type RequestQueuesItemType = {
    params: { methodName: string; params: ParamsType };
    resolve: (data: ParamsType) => void;
    reject: () => void;
  };

  const model: ModelType | undefined = inject("model");
  const instance = getCurrentInstance();
  const proxy = instance?.proxy as any;
  const state = proxy.$stateManager?.getState();
  watch(state, () => {
    console.log("ajaxData更新了", state);
    const { ajaxData } = state;
    if (ajaxData) {
      updateQueue(state.ajaxData);
    }
  });

  /* 并发模式------------------------------------------------------------------------- */
  const requestQueues = ref<{
    [key: string]: RequestQueuesItemType[];
  }>({});
  const requestInProgress = ref<{
    [key: string]: RequestQueuesItemType | boolean;
  }>({});
  const addRequestToQueue = (
    methodName: string,
    item: RequestQueuesItemType
  ) => {
    if (!requestQueues.value.hasOwnProperty(methodName)) {
      requestQueues.value[methodName] = [];
    }
    requestQueues.value[methodName].push(item);
    processQueue(methodName);
  };
  const processQueue = (methodName: string) => {
    if (
      requestInProgress.value[methodName] ||
      requestQueues.value[methodName].length === 0
    ) {
      return;
    }
    const queueItem = requestQueues.value[methodName].shift();
    if (queueItem) {
      requestInProgress.value[methodName] = queueItem;
      (model as ModelType).invoke(
        queueItem.params.methodName,
        queueItem.params.params
      );
    } else {
      requestInProgress.value[methodName] = false;
    }
  };

  /* 单线模式 ---------------------------------------------------------------------------------- */
  const singleRequestQueues = ref<RequestQueuesItemType[]>([]);
  const singleRequestInProgress = ref<RequestQueuesItemType | boolean>(false);
  const addSingleRequestToQueue = (item: RequestQueuesItemType) => {
    singleRequestQueues.value.push(item);
    processSingleQueue();
  };
  const processSingleQueue = () => {
    if (
      singleRequestInProgress.value ||
      singleRequestQueues.value.length === 0
    ) {
      return;
    }
    const queueItem = singleRequestQueues.value.shift();
    singleRequestInProgress.value = queueItem as RequestQueuesItemType;
    if (queueItem) {
      (model as ModelType).invoke(
        queueItem.params.methodName,
        queueItem.params.params
      );
    } else {
      singleRequestInProgress.value = false;
    }
  };

  /* 对外暴露的方法 ----------------------------------------------------------------------- */
  const invokeAsync: InvokeAsyncType = (methodName, params, config) => {
    return new Promise((resolve, reject) => {
      if (config?.noResponse) {
        (model as ModelType).invoke(methodName, params);
        return;
      }
      const item = { params: { methodName, params }, resolve, reject };
      if (appConfig.REQUEST_MODE === "concurrent") {
        addRequestToQueue(methodName, item as RequestQueuesItemType);
      } else {
        addSingleRequestToQueue(item as RequestQueuesItemType);
      }
    });
  };

  const updateMethodsField: string = appConfig.UPDATE_METHODS_FIELD;
  const updateQueue = async (props: ReturnDataType) => {
    const data = props?.data;
    if (!data) return;
    if (appConfig.REQUEST_MODE === "concurrent") {
      const type = data[updateMethodsField];
      if (!type) {
        console.error("并发模式需要后端返回请求方法的名称字段");
        return;
      }
      const queue = requestInProgress.value[type];
      if (!queue) {
        return;
      }
      try {
        (queue as RequestQueuesItemType)?.resolve(data);
      } catch (error) {
        console.log("这是后端单独主动推送事件数据----", data);
      }
      requestInProgress.value[type] = false;
      processQueue(type);
    } else {
      try {
        (singleRequestInProgress.value as RequestQueuesItemType)?.resolve(data);
      } catch (error) {
        console.log("这是后端单独主动推送事件数据----", data);
      }
      singleRequestInProgress.value = false;
      processSingleQueue();
    }
  };

  return invokeAsync;
}
